//
//  NSString+EMOEmoji.m
//  EmojiString
//
//  Created by GabrielMassana on 07/01/2016.
//  Copyright © 2016 GabrielMassana. All rights reserved.
//

#import "NSString+LLEmojiCheck.h"


@implementation NSString (LLEmojiCheck)

#pragma mark - EmojiRanges

- (NSArray *)emo_emojiRanges
{
    __block NSMutableArray *emojiRangesArray = [NSMutableArray new];

    [self enumerateSubstringsInRange:NSMakeRange(0,
                                                 [self length])
                             options:NSStringEnumerationByComposedCharacterSequences
                          usingBlock:^(NSString *substring,
                                       NSRange substringRange,
                                       NSRange enclosingRange,
                                       BOOL *stop) {
                              const unichar hs = [substring characterAtIndex:0];
                              // surrogate pair
                              if (0xd800 <= hs &&
                                  hs <= 0xdbff) {
                                  if (substring.length > 1) {
                                      const unichar ls = [substring characterAtIndex:1];
                                      const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                                      if (0x1d000 <= uc &&
                                          uc <= 0x1f9c0) {
                                          [emojiRangesArray addObject:[NSValue valueWithRange:substringRange]];
                                      }
                                  }
                              } else if (substring.length > 1) {
                                  const unichar ls = [substring characterAtIndex:1];
                                  if (ls == 0x20e3 ||
                                      ls == 0xfe0f ||
                                      ls == 0xd83c) {
                                      [emojiRangesArray addObject:[NSValue valueWithRange:substringRange]];
                                  }
                              } else {
                                  // non surrogate
                                  if (0x2100 <= hs &&
                                      hs <= 0x27ff) {
                                      [emojiRangesArray addObject:[NSValue valueWithRange:substringRange]];
                                  } else if (0x2B05 <= hs &&
                                             hs <= 0x2b07) {
                                      [emojiRangesArray addObject:[NSValue valueWithRange:substringRange]];
                                  } else if (0x2934 <= hs &&
                                             hs <= 0x2935) {
                                      [emojiRangesArray addObject:[NSValue valueWithRange:substringRange]];
                                  } else if (0x3297 <= hs &&
                                             hs <= 0x3299) {
                                      [emojiRangesArray addObject:[NSValue valueWithRange:substringRange]];
                                  } else if (hs == 0xa9 ||
                                             hs == 0xae ||
                                             hs == 0x303d ||
                                             hs == 0x3030 ||
                                             hs == 0x2b55 ||
                                             hs == 0x2b1c ||
                                             hs == 0x2b1b ||
                                             hs == 0x2b50) {
                                      [emojiRangesArray addObject:[NSValue valueWithRange:substringRange]];
                                  }
                              }
                          }];

    return emojiRangesArray;
}

#pragma mark - ContainsEmoji

- (BOOL)emo_containsEmoji
{
    __block BOOL containsEmoji = NO;

    [self enumerateSubstringsInRange:NSMakeRange(0,
                                                 [self length])
                             options:NSStringEnumerationByComposedCharacterSequences
                          usingBlock:^(NSString *substring,
                                       NSRange substringRange,
                                       NSRange enclosingRange,
                                       BOOL *stop) {
                              const unichar hs = [substring characterAtIndex:0];
                              // surrogate pair
                              if (0xd800 <= hs &&
                                  hs <= 0xdbff) {
                                  if (substring.length > 1) {
                                      const unichar ls = [substring characterAtIndex:1];
                                      const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                                      if (0x1d000 <= uc &&
                                          uc <= 0x1f9c0) {
                                          containsEmoji = YES;
                                      }
                                  }
                              } else if (substring.length > 1) {
                                  const unichar ls = [substring characterAtIndex:1];
                                  if (ls == 0x20e3 ||
                                      ls == 0xfe0f ||
                                      ls == 0xd83c) {
                                      containsEmoji = YES;
                                  }
                              } else {
                                  // non surrogate
                                  if (0x2100 <= hs &&
                                      hs <= 0x27ff) {
                                      containsEmoji = YES;
                                  } else if (0x2B05 <= hs &&
                                             hs <= 0x2b07) {
                                      containsEmoji = YES;
                                  } else if (0x2934 <= hs &&
                                             hs <= 0x2935) {
                                      containsEmoji = YES;
                                  } else if (0x3297 <= hs &&
                                             hs <= 0x3299) {
                                      containsEmoji = YES;
                                  } else if (hs == 0xa9 ||
                                             hs == 0xae ||
                                             hs == 0x303d ||
                                             hs == 0x3030 ||
                                             hs == 0x2b55 ||
                                             hs == 0x2b1c ||
                                             hs == 0x2b1b ||
                                             hs == 0x2b50) {
                                      containsEmoji = YES;
                                  }
                              }

                              if (containsEmoji) {
                                  *stop = YES;
                              }
                          }];

    return containsEmoji;
}

#pragma mark - PureEmojiString

- (BOOL)emo_isPureEmojiString
{
    if (self.length == 0) {
        return NO;
    }

    __block BOOL isPureEmojiString = YES;

    [self enumerateSubstringsInRange:NSMakeRange(0,
                                                 [self length])
                             options:NSStringEnumerationByComposedCharacterSequences
                          usingBlock:^(NSString *substring,
                                       NSRange substringRange,
                                       NSRange enclosingRange,
                                       BOOL *stop) {
                              BOOL containsEmoji = NO;
                              const unichar hs = [substring characterAtIndex:0];
                              // surrogate pair
                              if (0xd800 <= hs &&
                                  hs <= 0xdbff) {
                                  if (substring.length > 1) {
                                      const unichar ls = [substring characterAtIndex:1];
                                      const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                                      if (0x1d000 <= uc &&
                                          uc <= 0x1f9c0) {
                                          containsEmoji = YES;
                                      }
                                  }
                              } else if (substring.length > 1) {
                                  const unichar ls = [substring characterAtIndex:1];
                                  if (ls == 0x20e3 ||
                                      ls == 0xfe0f ||
                                      ls == 0xd83c) {
                                      containsEmoji = YES;
                                  }
                              } else {
                                  // non surrogate
                                  if (0x2100 <= hs &&
                                      hs <= 0x27ff) {
                                      containsEmoji = YES;
                                  } else if (0x2B05 <= hs &&
                                             hs <= 0x2b07) {
                                      containsEmoji = YES;
                                  } else if (0x2934 <= hs &&
                                             hs <= 0x2935) {
                                      containsEmoji = YES;
                                  } else if (0x3297 <= hs &&
                                             hs <= 0x3299) {
                                      containsEmoji = YES;
                                  } else if (hs == 0xa9 ||
                                             hs == 0xae ||
                                             hs == 0x303d ||
                                             hs == 0x3030 ||
                                             hs == 0x2b55 ||
                                             hs == 0x2b1c ||
                                             hs == 0x2b1b ||
                                             hs == 0x2b50) {
                                      containsEmoji = YES;
                                  }
                              }

                              if (!containsEmoji) {
                                  isPureEmojiString = NO;
                                  *stop = YES;
                              }
                          }];

    return isPureEmojiString;
}

#pragma mark - EmojiCount

- (NSInteger)emo_emojiCount
{
    __block NSInteger emojiCount = 0;

    [self enumerateSubstringsInRange:NSMakeRange(0,
                                                 [self length])
                             options:NSStringEnumerationByComposedCharacterSequences
                          usingBlock:^(NSString *substring,
                                       NSRange substringRange,
                                       NSRange enclosingRange,
                                       BOOL *stop) {
                              const unichar hs = [substring characterAtIndex:0];
                              // surrogate pair
                              if (0xd800 <= hs &&
                                  hs <= 0xdbff) {
                                  if (substring.length > 1) {
                                      const unichar ls = [substring characterAtIndex:1];
                                      const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                                      if (0x1d000 <= uc &&
                                          uc <= 0x1f9c0) {
                                          emojiCount = emojiCount + 1;
                                      }
                                  }
                              } else if (substring.length > 1) {
                                  const unichar ls = [substring characterAtIndex:1];
                                  if (ls == 0x20e3 ||
                                      ls == 0xfe0f ||
                                      ls == 0xd83c) {
                                      emojiCount = emojiCount + 1;
                                  }
                              } else {
                                  // non surrogate
                                  if (0x2100 <= hs &&
                                      hs <= 0x27ff) {
                                      emojiCount = emojiCount + 1;
                                  } else if (0x2B05 <= hs &&
                                             hs <= 0x2b07) {
                                      emojiCount = emojiCount + 1;
                                  } else if (0x2934 <= hs &&
                                             hs <= 0x2935) {
                                      emojiCount = emojiCount + 1;
                                  } else if (0x3297 <= hs &&
                                             hs <= 0x3299) {
                                      emojiCount = emojiCount + 1;
                                  } else if (hs == 0xa9 ||
                                             hs == 0xae ||
                                             hs == 0x303d ||
                                             hs == 0x3030 ||
                                             hs == 0x2b55 ||
                                             hs == 0x2b1c ||
                                             hs == 0x2b1b ||
                                             hs == 0x2b50) {
                                      emojiCount = emojiCount + 1;
                                  }
                              }
                          }];

    return emojiCount;
}


@end
